package com.zHan.system.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zHan.common.utils.MD5Util;
import com.zHan.common.utils.ThreadLocalUtil;
import com.zHan.model.dto.SysUserQueryDto;
import com.zHan.model.dto.UpdatePwdDto;
import com.zHan.model.system.SysUser;
import com.zHan.model.system.SysUserDept;
import com.zHan.model.system.SysUserPost;
import com.zHan.model.system.SysUserRole;
import com.zHan.model.vo.RouterVo;
import com.zHan.model.vo.UserDetailsVo;
import com.zHan.system.exception.MyException;
import com.zHan.system.mapper.SysUserDeptMapper;
import com.zHan.system.mapper.SysUserMapper;
import com.zHan.system.mapper.SysUserPostMapper;
import com.zHan.system.mapper.SysUserRoleMapper;
import com.zHan.system.service.ISysMenuService;
import com.zHan.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author zHan
 * @since 2023-06-22
 */
@Service
@Transactional
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysUserDeptMapper userDeptMapper;

    @Autowired
    private SysUserPostMapper userPostMapper;

    /**
     * 分页条件查询
     *
     * @param page
     * @param pageSize
     * @param userQueryVo
     * @return
     */
    @Override
    public Page<SysUser> selectPageQuery(Long page, Long pageSize, SysUserQueryDto userQueryVo) {
        // 创建Page对象
        Page<SysUser> pageInfo = new Page<>(page, pageSize);
        // 条件查询
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //准备参数
        String keyword = userQueryVo.getKeyword();
        String timeBegin = userQueryVo.getCreateTimeBegin();
        String timeEnd = userQueryVo.getCreateTimeEnd();
        Integer status = userQueryVo.getStatus();
        Integer sex = userQueryVo.getSex();
        if (!StringUtils.isEmpty(keyword)) {
            lambdaQueryWrapper.like(SysUser::getName, keyword)
                    .or().like(SysUser::getUsername, keyword)
                    .or().like(SysUser::getPhone, keyword);
        }

        if (!StringUtils.isEmpty(timeBegin)) {
            lambdaQueryWrapper.ge(SysUser::getCreateTime, timeBegin);
        }

        if (!StringUtils.isEmpty(timeEnd)) {
            lambdaQueryWrapper.lt(SysUser::getCreateTime, timeEnd);
        }

        if (sex != null) {
            lambdaQueryWrapper.eq(SysUser::getSex, sex);
        }

        if (status != null) {
            lambdaQueryWrapper.eq(SysUser::getStatus, status);
        }
        //执行方法
        this.page(pageInfo, lambdaQueryWrapper);
        return pageInfo;
    }

    /**
     * 更改用户状态
     *
     * @param id
     * @param status
     * @return
     */
    @Override
    public boolean updateStatus(Long id, Integer status) {
        SysUser user = userMapper.selectById(id);
        user.setStatus(status);
        return this.updateById(user);
    }

    /**
     * 根据username查询数据
     *
     * @param username
     * @return
     */
    @Override
    public SysUser getUserInfoByUserName(String username) {
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysUser::getUsername, username);
        return userMapper.selectOne(lambdaQueryWrapper);
    }

    /**
     * 根据username查询用户信息（基本信息、菜单权限和按钮权限信息）
     *
     * @param username
     * @return
     */
    @Override
    public Map<String, Object> getUserByUserName(String username) {
        // 查询用户基本信息
        SysUser sysUser = this.getUserInfoByUserName(username);
        // 根据userId查询菜单权限值
        List<RouterVo> routerList = menuService.getUserMenuList(sysUser.getId());
        // 根据userId查询按钮权限值
        List<String> buttonList = menuService.getUserButtonList(sysUser.getId());
        Map<String, Object> map = new HashMap<>();
        map.put("name", username);
        map.put("trueName", sysUser.getName());
        map.put("avatar", sysUser.getHeadUrl());
        map.put("roles", sysUser.getRoleList());
        map.put("introduction", sysUser.getDescription());

        // 菜单权限数据
        map.put("routers", routerList);
        // 按钮权限数据
        map.put("buttons", buttonList);
        return map;
    }

    /**
     * 更新用户头像
     *
     * @param avatarUrl
     * @return
     */
    @Override
    public boolean updateAvatar(String avatarUrl) {
        Map<String, String> map = ThreadLocalUtil.get();
        // 获得用户的id
        String userId = map.get("userId");
        if (userId == null) {
            throw new MyException(20001, "用户不存在");
        }
        // 修改用户头像
        SysUser user = userMapper.selectById(userId);
        user.setHeadUrl(avatarUrl);
        return this.updateById(user);
    }

    /**
     * 重置密码
     *
     * @param updatePwdDto
     * @return
     */
    @Override
    public boolean updatePwd(UpdatePwdDto updatePwdDto, String token) {
        // 获取参数
        String oldPwd = updatePwdDto.getOldPwd();
        String newPwd = updatePwdDto.getNewPwd();
        String rePwd = updatePwdDto.getRePwd();

        // 参数校验
        if (!StringUtils.hasText(oldPwd)) {
            throw new MyException(20001, "旧密码不能为空");
        }
        if (!StringUtils.hasText(newPwd)) {
            throw new MyException(20001, "新密码不能为空");
        }
        if (!StringUtils.hasText(rePwd)) {
            throw new MyException(20001, "重新输入的新密码不能为空");
        }
        // 获取username
        Map<String, String> map = ThreadLocalUtil.get();
        String username = map.get("username");
        // 根据username查询数据
        SysUser user = this.getUserInfoByUserName(username);
        //如果数据为空
        if (user == null) {
            throw new MyException(20001, "用户不存在");
        }
        // 判断旧密码是否正确
        String encryptOldPwd = MD5Util.encrypt(oldPwd);
        if (!encryptOldPwd.equals(user.getPassword())) {
            throw new MyException(20001, "修改密码失败，旧密码不正确");
        }
        // 判断新密码和重复密码是否正确
        if (!newPwd.equals(rePwd)) {
            throw new MyException(20001, "修改密码失败，两次填写的新密码不一样");
        }

        // 修改密码
        user.setPassword(MD5Util.encrypt(newPwd));
        return this.updateById(user);
    }

    /**
     * 获取用户详情
     *
     * @param username
     * @return
     */
    @Override
    public UserDetailsVo getUserDetails(String username) {
        // 获取用户基本信息
        SysUser user = this.getUserInfoByUserName(username);
        // 封装vo对象
        UserDetailsVo userDetailsVo = new UserDetailsVo();
        BeanUtils.copyProperties(user, userDetailsVo);
        return userDetailsVo;
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     */
    @Override
    public boolean removeUserById(Long id) {
        //查询用户信息，确定是否可以删除
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(SysUser::getStatus, 1)
                .eq(SysUser::getId, id);
        //不能删除，抛出业务异常
        if (this.getOne(lambdaQueryWrapper) != null) {
            throw new MyException(201, "用户在启用状态，不能删除");
        }

        try {
            //先删除用户表中的信息
            this.removeById(id);
            //再删除其他表中的数据
            userRoleMapper.delete(Wrappers.<SysUserRole>lambdaQuery()
                    .eq(SysUserRole::getUserId, id));
            userDeptMapper.delete(Wrappers.<SysUserDept>lambdaQuery()
                    .eq(SysUserDept::getUserId, id));
            userPostMapper.delete(Wrappers.<SysUserPost>lambdaQuery()
                    .eq(SysUserPost::getUserId, id));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return true;
    }

    /**
     * 批量删除用户
     *
     * @param idList
     * @return
     */
    @Override
    public boolean removeUserByIds(List<Long> idList) {
        //查询用户信息，确定是否可以删除
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(SysUser::getStatus, 1)
                .in(SysUser::getId, idList);
        //不能删除，抛出业务异常
        if (this.count(lambdaQueryWrapper) > 0) {
            throw new MyException(201, "有用户在启用状态，不能删除");
        }

        try {
            //先删除用户表中的信息
            this.removeByIds(idList);
            //再删除其他表中的数据
            userRoleMapper.delete(Wrappers.<SysUserRole>lambdaQuery()
                    .in(SysUserRole::getUserId, idList));
            userDeptMapper.delete(Wrappers.<SysUserDept>lambdaQuery()
                    .in(SysUserDept::getUserId, idList));
            userPostMapper.delete(Wrappers.<SysUserPost>lambdaQuery()
                    .in(SysUserPost::getUserId, idList));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return true;
    }
}
